home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’88 / Slider FKEY / drag.p next >
Encoding:
Text File  |  1988-06-17  |  12.2 KB  |  408 lines  |  [TEXT/MPS ]

  1. {    'Slider' is the mental product of Bill Johnson & Ron Duritsch 
  2.     notes: put the accompanying sound file in your system folder for maximum effect }
  3.  
  4. {$R+}            { range checking }
  5.  
  6. UNIT Drag;
  7.  
  8.  
  9. INTERFACE
  10.  
  11. USES
  12.       MemTypes, QuickDraw, OSIntf, ToolIntf, SANE;
  13.  
  14. PROCEDURE DragIt;
  15.  
  16.  
  17. IMPLEMENTATION
  18.  
  19. CONST
  20.     nearInfinity    = 32000;
  21.     SlopSize        = 25;
  22.     OutOfBounds    = $8000;
  23.     allKeyEvents    = keyDownMask + keyUpMask + autoKeyMask;
  24.  
  25. TYPE
  26.     WindArray = ARRAY[1..32] OF WindowPtr;    {    this data structure stores the window pointers that
  27.                                                                             have been selected with the mouse. The first pointer
  28.                                                                             in the array (WindArray[1]) must be the pointer to
  29.                                                                             the selected window closest to the front window. }
  30.  
  31. PROCEDURE Get3Cursors (VAR svCrs: Cursor; VAR hndCrs: Cursor; VAR scndCrs: Cursor);    FORWARD;
  32. PROCEDURE GetScreenSize (topWind: windowPtr; VAR screenPerim: rect);                            FORWARD;
  33. FUNCTION LoadSound (VAR SoundBuffer: Ptr; VAR sndSize: longint): boolean;                        FORWARD;
  34. FUNCTION InsertWPtr(HitWPtr: windowPtr; VAR PtrArray: WindArray; VAR NumWind: integer): boolean;        FORWARD;
  35. PROCEDURE SumWRgnsBelow (StartWPtr: windowPtr; DragRegion: RgnHandle);                        FORWARD;
  36. PROCEDURE MoveWindBelow (StartWPtr: windowPtr; hor, ver: integer; dragArea: rect);        FORWARD;
  37. PROCEDURE MoveWindSel (VAR PtrArray: WindArray; NumWind, hor, ver: integer; dragArea: rect);    FORWARD;
  38.  
  39.  
  40.  
  41. PROCEDURE DragIt;
  42.  
  43. VAR
  44.     theEvent                        : EventRecord;
  45.     WMgrPort, savePort        : GrafPtr;
  46.     HitWindPtr, topWindPtr    : WindowPtr;
  47.     currentWPeek                : windowPeek;
  48.     WPtrArray                    : WindArray;
  49.     DragRgn, ExistClipRgn    : RgnHandle;
  50.     mousePos                        : Point;
  51.     limitRect, slopRect        : rect;
  52.     screenBounds, dragLim    : rect;
  53.     thePart    , index                : integer;
  54.     NumWSel, vMov, hMov    : integer;
  55.     mainCursor, saveCursr    : Cursor;
  56.     secondCursor                : Cursor;
  57.     DropOut, haveSound        : boolean;
  58.     SoundPointer                : Ptr;
  59.     sndSize, longPos            : longint;
  60.  
  61. BEGIN
  62.     topWindPtr := FrontWindow;                                { this does not change }
  63.  
  64.     GetPort(savePort);
  65.     DragRgn := NewRgn;
  66.     ExistClipRgn := NewRgn;
  67.     GetClip(ExistClipRgn);
  68.  
  69.     GetScreenSize (topWindPtr, screenBounds);
  70.     dragLim := screenBounds;
  71.     InsetRect (dragLim, 20, 0);
  72.  
  73.     GetWMgrPort(WMgrPort);
  74.     SetPort(WMgrPort);
  75.     SetPortBits(WMgrPort^.portBits);
  76.     ClipRect(WMgrPort^.portRect);
  77.         
  78.     Get3Cursors (saveCursr, mainCursor, secondCursor);
  79.     SetCursor (mainCursor);
  80.  
  81.     haveSound := LoadSound (SoundPointer, sndSize);
  82.  
  83.     NumWSel := 0;
  84.     DropOut := FALSE;
  85.     WPtrArray[1] := topWindPtr;    { init to FrontWindow to prevent 'ClipAbove' call when no windows sel }
  86.  
  87.     REPEAT
  88.         IF GetNextEvent(mDownMask, theEvent) then begin
  89.             mousePos := theEvent.where;
  90.             thePart := FindWindow (theEvent.where, hitWindPtr);
  91.  
  92.             IF (haveSound)
  93.                 then StartSound (SoundPointer, sndSize, NIL);                { play asynchronous sound }
  94.  
  95.             if (thePart < inSysWindow)
  96.                 then begin
  97.                     sysBeep (1);
  98.                     Dropout := TRUE;
  99.                     end
  100.                 else begin
  101.                     if (BitAnd(theEvent.modifiers, shiftKey) <> 0)
  102.                         then begin
  103.                             if (InsertWPtr(HitWindPtr, WPtrArray, NumWSel))
  104.                                 then begin
  105.                                     SetCursor (secondCursor);
  106.                                     currentWPeek := WindowPeek (HitWindPtr);
  107.                                     UnionRgn (currentWPeek^.StrucRgn, DragRgn, DragRgn);
  108.                                     end;
  109.                             end
  110.                         else begin
  111.                             Dropout := TRUE;
  112.                             if (BitAnd(theEvent.modifiers, optionKey) <> 0)
  113.                                 then begin
  114.                                     SetRectRgn (DragRgn, 0, 0, 0, 0);        { empty region of accumulated regions }
  115.                                     SumWRgnsBelow (hitWindPtr, DragRgn);
  116.                                     WPtrArray[1] := hitWindPtr;
  117.                                     end
  118.                                 else begin
  119.                                     if (NumWSel = 0)
  120.                                         then SumWRgnsBelow (topWindPtr, DragRgn)
  121.                                         else begin
  122.                                             if (InsertWPtr(HitWindPtr, WPtrArray, NumWSel))
  123.                                                 then begin
  124.                                                     SetCursor (secondCursor);
  125.                                                     currentWPeek := WindowPeek (HitWindPtr);
  126.                                                     UnionRgn (currentWPeek^.StrucRgn, DragRgn, DragRgn);
  127.                                                     end;
  128.                                             end;
  129.                                     end;
  130.                             end;
  131.  
  132.                     ClipRect(WMgrPort^.portRect);
  133.                     if (WPtrArray[1] <> topWindPtr)        { top selected window must be in 'WPtrArray[1]' }
  134.                         then ClipAbove (WindowPeek (WPtrArray[1]));
  135.  
  136.                     IF (BitAnd(theEvent.modifiers, cmdKey) <> 0)
  137.                         then SetRect (dragLim, -nearInfinity, -nearInfinity, nearInfinity, nearInfinity);
  138.                     with dragLim do begin
  139.                         SetRect (limitRect, left, top, right, bottom);
  140.                         SetRect (slopRect, left - SlopSize, top - 45, right + SlopSize, bottom + SlopSize);
  141.                         end;
  142.  
  143.                     longPos := DragGrayRgn (DragRgn, mousePos, limitRect, slopRect, 0, NIL);
  144.  
  145.                     IF (longPos <> OutOfBounds) then begin
  146.                         hMov := LoWord (longPos);
  147.                         vMov := HiWord (longPos);
  148.                         IF (BitAnd(theEvent.modifiers, shiftKey) <> 0)
  149.                             then begin
  150.                                 IF (ABS (hMov) + ABS (vMov) > 5) then begin
  151.                                     Dropout := TRUE;
  152.                                     MoveWindSel (WPtrArray, NumWSel, hMov, vMov, dragLim);
  153.                                     end;
  154.                                 end
  155.                             else begin
  156.                                 IF (BitAnd(theEvent.modifiers, optionKey) <> 0)
  157.                                     then MoveWindBelow (hitWindPtr, hMov, vMov, dragLim)
  158.                                     else begin
  159.                                         if (NumWSel = 0)
  160.                                             then MoveWindBelow (topWindPtr, hMov, vMov, dragLim)
  161.                                             else MoveWindSel (WPtrArray, NumWSel, hMov, vMov, dragLim);
  162.                                         end;
  163.                                 end;
  164.                         end;        { IF (longPos <> OutOfBounds) ... }
  165.                 end;        { if (thePart < inSysWindow)... }
  166.             SetCursor (mainCursor);
  167.             end;
  168.     UNTIL Dropout;
  169.  
  170.     IF (haveSound)
  171.         then DisposPtr (SoundPointer);
  172.     SetPort (savePort);
  173.     SetClip (ExistClipRgn);
  174.     DisposeRgn (ExistClipRgn);
  175.     DisposeRgn (DragRgn);
  176.     flushEvents (allKeyEvents, 0);            { in case the user re-selected the FKEY while we were in here }
  177.     SetCursor (saveCursr);
  178. END;
  179.  
  180.  
  181.  
  182.  
  183. PROCEDURE Get3Cursors (VAR svCrs: Cursor; VAR hndCrs: Cursor; VAR scndCrs: Cursor);
  184. CONST
  185.     LoMemCrsrLoc    = $844;
  186. VAR
  187.     CrsrPtr    : ^Cursor;
  188. BEGIN
  189.     CrsrPtr := pointer (LoMemCrsrLoc);
  190.     svCrs := CrsrPtr^;
  191.  
  192.     StuffHex (ptr (@hndCrs), 'AAAA0000B030334E' );
  193.     StuffHex (ptr (longint (@hndCrs) + 8), '84C954C982490249');
  194.     StuffHex (ptr (longint (@hndCrs) + 16), '8D01130091000800');
  195.     StuffHex (ptr (longint (@hndCrs) + 24), '8400040082004100');
  196.     StuffHex (ptr (longint (@hndCrs) + 32), 'AAAA0000B030337E');
  197.     StuffHex (ptr (longint (@hndCrs) + 40), '87FF57FF83FF03FF');
  198.     StuffHex (ptr (longint (@hndCrs) + 48), '8FFF1FFF9FFF0FFF');
  199.     StuffHex (ptr (longint (@hndCrs) + 56), '87FF07FF83FF41FF');
  200.     StuffHex (ptr (longint (@hndCrs) + 64), '00050007');
  201.  
  202.     StuffHex (ptr (@scndCrs), '000000000030034E' );
  203.     StuffHex (ptr (longint (@scndCrs) + 8), '04C904C902490249');
  204.     StuffHex (ptr (longint (@scndCrs) + 16), '0D01130011000800');
  205.     StuffHex (ptr (longint (@scndCrs) + 24), '0400040002000100');
  206.     StuffHex (ptr (longint (@scndCrs) + 32), '000000000030037E');
  207.     StuffHex (ptr (longint (@scndCrs) + 40), '07FF07FF03FF03FF');
  208.     StuffHex (ptr (longint (@scndCrs) + 48), '0FFF1FFF1FFF0FFF');
  209.     StuffHex (ptr (longint (@scndCrs) + 56), '07FF07FF03FF01FF');
  210.     StuffHex (ptr (longint (@scndCrs) + 64), '00050007');
  211. END;
  212.  
  213.  
  214.  
  215.  
  216. PROCEDURE GetScreenSize (topWind: windowPtr; VAR screenPerim: rect);
  217. TYPE
  218.     WStatePtr = ^WStateData;
  219.     WStateHdl = ^WStatePtr;
  220. VAR
  221.     windRect        : rect;
  222.     ZoomDataHdl    : WStateHdl;
  223.     tempWindPtr    : windowPtr;
  224. BEGIN
  225.     SetRect (windRect, 40, 0, 100, 100);
  226.     tempWindPtr := NewWindow (nil, windRect, 'x', FALSE, 8, topWind, TRUE, 0);
  227.     ZoomDataHdl := WStateHdl (WindowPeek (tempWindPtr)^.dataHandle);
  228.     screenPerim.left := ZoomDataHdl^^.stdState.left - 2;
  229.     screenPerim.top := ZoomDataHdl^^.stdState.top;
  230.     screenPerim.Right := ZoomDataHdl^^.stdState.right + 2;
  231.     screenPerim.Bottom := ZoomDataHdl^^.stdState.bottom + 2;
  232.     disposeWindow (tempWindPtr);
  233. END;
  234.  
  235.  
  236.  
  237.  
  238. FUNCTION LoadSound (VAR SoundBuffer: Ptr; VAR sndSize: longint): boolean;
  239.     { This code trys to load a sound file. To allow some selection of playback rate, it will look for 2
  240.       different files.  If it finds a file called Sound22, it will load/play it at a sampling rate of 22 kHz.
  241.       If thats not found, it will look for Sound11, and if found it will be played at 11 kHz.    }  
  242. VAR
  243.     FFSound        : FFSynthPtr;
  244.     soundRef        : integer;
  245.     rateDiv, rc    : integer;
  246.     Count, fSize    : longint;
  247. BEGIN
  248.     rateDiv := 1;        { assume 22 kHz sampling }
  249.     LoadSound := FALSE;
  250.     rc := FSOpen ('Sound22', 0, soundRef);
  251.     IF (rc <> noErr) THEN BEGIN
  252.         rateDiv := 2;        { set for 11 kHz playback }
  253.         rc := FSOpen ('Sound11', 0, soundRef);
  254.         END;
  255.         
  256.     IF (rc = noErr)
  257.         THEN BEGIN
  258.             LoadSound := TRUE;
  259.             rc := GetEOF( soundRef, fSize );    { get file size }
  260.             sndSize := fSize + 6;                { size of sound buffer }
  261.             SoundBuffer := NewPtr (sndSize);
  262.             FFSound := FFSynthPtr (SoundBuffer);
  263.             FFSound^.mode := ffMode;                                { free form synthesizer }
  264.             FFSound^.count := FixRatio (1, rateDiv);            { fill in the fixed binary playback rate }
  265.             Count := fSize;
  266.             rc := FSRead (soundREf, Count, @FFSound^.waveBytes);
  267.             rc := FSClose (soundRef);
  268.             END;
  269. END;
  270.  
  271.  
  272.  
  273. FUNCTION InsertWPtr(HitWPtr            : windowPtr;
  274.                                 VAR PtrArray    : WindArray;
  275.                                 VAR NumWind    : integer): boolean;
  276. {    purpose     _IF_ ptr not in list, put window ptr 'HitWPtr' in list 'PtrArray' & add 1 to 'NumWind'
  277.                     ALWAYS keep ptr to highest selected window in 'PtrArray[1]'    }
  278. VAR
  279.     ctr        : integer;
  280.     match    : boolean;
  281.     cWPeek    : windowPeek;
  282.     cWPtr    : WindowPtr;
  283.     HiPtr    : WindowPtr;
  284. BEGIN
  285.     if (NumWind = 0)
  286.         then begin
  287.             NumWind := 1;
  288.             PtrArray[1] := HitWPtr;
  289.             InsertWPtr := TRUE;
  290.             end
  291.         else begin
  292.             ctr := 0;
  293.             REPEAT
  294.                 ctr := ctr + 1;
  295.                 match := (HitWPtr = PtrArray[ctr]);
  296.             UNTIL (ctr = NumWind) or (match);
  297.  
  298.             if (match)
  299.                 then InsertWPtr := FALSE
  300.                 else begin
  301.                     NumWind := NumWind + 1;
  302.                     InsertWPtr := TRUE;
  303.  
  304.                     HiPtr := PtrArray[1];
  305.                     cWPtr := HitWPtr;
  306.                     REPEAT
  307.                         cWPeek := WindowPeek (cWPtr);
  308.                         cWPtr := windowPtr(cWPeek^.nextWindow);
  309.                     UNTIL (cWPtr = HiPtr) or (cWPtr = NIL);
  310.                     if (cWPtr = HiPtr)
  311.                         then begin
  312.                             PtrArray[NumWind] := HiPtr;
  313.                             PtrArray[1] := HitWPtr;
  314.                             end
  315.                         else PtrArray[NumWind] := HitWPtr;
  316.                     end;
  317.             end;
  318. END;
  319.  
  320.  
  321. PROCEDURE SumWRgnsBelow (StartWPtr: windowPtr; DragRegion: RgnHandle);
  322. {    purpose     return in 'DragRegion' a region including all windows after & incl. window 'StartWPtr'    }
  323. VAR
  324.     currWPeek    : windowPeek;
  325.     PrevWPeek    : windowPeek;
  326.     currWindPtr    : WindowPtr;
  327. BEGIN
  328.     currWindPtr := StartWPtr;
  329.     REPEAT
  330.         currWPeek := WindowPeek (currWindPtr);
  331.         UnionRgn (currWPeek^.StrucRgn, DragRegion, DragRegion);
  332.         PrevWPeek := currWPeek;
  333.         currWindPtr := windowPtr(PrevWPeek^.nextWindow);
  334.     UNTIL (currWindPtr = NIL);
  335. END;
  336.  
  337.  
  338.  
  339. PROCEDURE MoveWindBelow (StartWPtr    : windowPtr;
  340.                                              hor, ver        : integer;
  341.                                              dragArea        : rect);
  342. {    purpose      move windows -> 'StartWPtr' to last window in the window list by 'hor','ver'    }
  343. VAR
  344.     PrevWPeek    : windowPeek;
  345.     currWindPtr    : WindowPtr;
  346.     origLoc            : point;
  347.     leftBound        : integer;
  348. BEGIN
  349.     currWindPtr := StartWPtr;
  350.     REPEAT
  351.         SetPort (grafPtr(currWindPtr));
  352.         origLoc := currWindPtr^.portrect.topleft;
  353.         LocalToGlobal (origLoc);
  354.         origLoc.h := origLoc.h + hor;
  355.         origLoc.v := origLoc.v + ver;
  356.         IF (origLoc.v < dragArea.top)
  357.             then origLoc.v := dragArea.top;
  358.         if (origLoc.v > dragArea.bottom)
  359.             then origLoc.v := dragArea.bottom;
  360.         leftBound := dragArea.left - GrafPtr(currWindPtr)^.portRect.right
  361.                                                                     + GrafPtr(currWindPtr)^.portRect.left;
  362.         if (origLoc.h < leftBound)
  363.             then origLoc.h := leftBound;
  364.         if (origLoc.h > dragArea.right)
  365.             then origLoc.h := dragArea.right;
  366.         MoveWindow(currWindPtr, origLoc.h, origLoc.v, FALSE);
  367.         PrevWPeek := WindowPeek(currWindPtr);
  368.         currWindPtr := windowPtr(PrevWPeek^.nextWindow);
  369.     UNTIL (currWindPtr = NIL);
  370. END;
  371.  
  372.  
  373.  
  374. PROCEDURE MoveWindSel (VAR PtrArray    : WindArray;
  375.                                          NumWind            : integer;
  376.                                          hor, ver            : integer;
  377.                                          dragArea            : rect);
  378. {    purpose      move windows in list 'PtrArray' by 'hor' & 'ver'    }
  379. VAR
  380.     origLoc        : point;
  381.     index        : integer;
  382.     leftBound    : integer;
  383. BEGIN
  384.     FOR index := 1 to NumWind DO begin
  385.         SetPort (grafPtr(PtrArray[index]));
  386.         origLoc := PtrArray[index]^.portrect.topleft;
  387.         LocalToGlobal (origLoc);
  388.         origLoc.h := origLoc.h + hor;
  389.         origLoc.v := origLoc.v + ver;
  390.         IF (origLoc.v < dragArea.top)
  391.             then origLoc.v := dragArea.top;
  392.         if (origLoc.v > dragArea.bottom)
  393.             then origLoc.v := dragArea.bottom;
  394.         leftBound := dragArea.left - GrafPtr(PtrArray[index])^.portRect.right
  395.                                                                     + GrafPtr(PtrArray[index])^.portRect.left;
  396.         if (origLoc.h < leftBound)
  397.             then origLoc.h := leftBound;
  398.         if (origLoc.h > dragArea.right)
  399.             then origLoc.h := dragArea.right;
  400.         MoveWindow (PtrArray[index], origLoc.h, origLoc.v, FALSE);
  401.         end;
  402. END;
  403.  
  404.  
  405.  
  406. END.
  407.  
  408.